home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ldb.zip / BINDER.CPP < prev    next >
C/C++ Source or Header  |  1991-10-18  |  13KB  |  685 lines

  1. /*
  2.  
  3.     binder.cpp
  4.     10-18-91
  5.     Loose Data Binder v 1.4
  6.  
  7.     Copyright 1991
  8.     John W. Small
  9.     All rights reserved
  10.  
  11.     PSW / Power SoftWare
  12.     P.O. Box 10072
  13.     McLean, Virginia 22102 8072 USA
  14.  
  15.     John Small
  16.     Voice: (703) 759-3838
  17.     CIS: 73757,2233
  18.  
  19. */
  20.  
  21.  
  22. #include <string.h>
  23. #include "binder.hpp"
  24.  
  25. void Binder::construct(unsigned flags, unsigned maxNodes,
  26.     unsigned limit, unsigned delta)
  27. {
  28.     curNode = first = nodes = 0;
  29.     comparE = BDRcomparE0;
  30.  
  31. /*
  32.     The following relationships are maintained
  33.     during operation of a binder:
  34.  
  35.     1 <= delta <= lowLimit <= limit <= maxNodes
  36.         <= BDR_MAXNODES
  37.     lowThreshold = lowLimit - delta;
  38. */
  39.  
  40.     if (maxNodes > BDR_MAXNODES)
  41.         maxNodes = BDR_MAXNODES;
  42.     if (limit > maxNodes)
  43.         limit = maxNodes;
  44.     if (delta > limit)
  45.         delta = limit;
  46.     if (!delta)  {
  47.         delta = 1;
  48.         if (limit < delta)
  49.             limit = delta;
  50.         if (maxNodes < limit)
  51.             maxNodes = limit;
  52.     }
  53.     if ((linkS = new voiD[limit]) == voiDV0)
  54.         this->limit = lowLimit = lowThreshold
  55.             = this->delta = this->maxNodes
  56.             = this->flags = 0;
  57.     else  {
  58.         this->limit = limit;
  59.         this->delta = delta;
  60.         this->maxNodes = maxNodes;
  61.         lowLimit = limit;
  62.         lowThreshold = lowLimit - delta;
  63.         this->flags = ((flags & BDR_OK_FREE) 
  64.             | BDR_SORTED);
  65.     }
  66. }
  67.  
  68. Binder::Binder(voiDV argv, int argc, unsigned flags)
  69. {
  70.     construct(flags,BDR_MAXNODES,argc,BDR_DELTA);
  71.     if (argv) if (argc > 0)
  72.         while (argc--)
  73.             push(argv[argc]);
  74.     else
  75.         for (argc = 0; insQ(argv[argc]); argc++);
  76. }
  77.  
  78. voiDV Binder::vector()
  79. {
  80.     voiDV V = voiDV0;
  81.  
  82.     if (nodes) if ((V = new voiD[nodes+1]) != voiDV0)  {
  83.         for (unsigned i = 0; i < nodes; i++)
  84.             V[i] = atGet(i);
  85.         V[i] = voiD0;
  86.     }
  87.     return V;
  88. }
  89.  
  90. Binder::~Binder()
  91. {
  92.     if (flags & BDR_OK_FREE)
  93.         allFree();
  94.     else
  95.         allDel();
  96.     if (linkS)
  97.         delete linkS;
  98. }
  99.  
  100. unsigned Binder::setLimit(unsigned newLimit)
  101. {
  102.     voiDV newLinkS;
  103.     unsigned i;
  104.  
  105.     if (newLimit < nodes)
  106.         newLimit = nodes;
  107.     else if (newLimit > maxNodes)
  108.         newLimit = maxNodes;
  109.     if (newLimit < delta)
  110.         newLimit = delta;
  111.     if (!linkS || !newLimit || newLimit == limit)
  112.         return 0;
  113.     if ((newLinkS = new voiD[newLimit]) == voiDV0)
  114.         return 0;
  115.     if ((i = limit - first) > nodes)
  116.         i = nodes;
  117.     memcpy(newLinkS,&linkS[first],sizeof(linkS[0])*i);
  118.     /* copy wrap around */
  119.     if (i < nodes)
  120.         memcpy(&newLinkS[i],linkS,
  121.             sizeof(linkS[0])*(nodes-i));
  122.     if (newLimit > limit)
  123.         if (newLimit - delta > limit)
  124.             lowLimit = newLimit - delta;
  125.         else
  126.             lowLimit = limit;
  127.     else
  128.         if (newLimit - delta > delta)
  129.             lowLimit = newLimit - delta;
  130.         else
  131.             lowLimit = delta;
  132.     lowThreshold = lowLimit - delta;
  133.     delete linkS;
  134.     linkS = newLinkS;
  135.     limit = newLimit;
  136.     first = 0;
  137.     return limit;
  138. }
  139.  
  140. unsigned Binder::setDelta(unsigned newDelta)
  141. {
  142.     return ((newDelta && newDelta <= lowLimit)?
  143.         delta = newDelta : 0);
  144. }
  145.  
  146. unsigned Binder::setMaxNodes(unsigned newMaxNodes)
  147. {
  148.     return ((newMaxNodes >= limit)?
  149.         (maxNodes = (newMaxNodes
  150.         > BDR_MAXNODES)? BDR_MAXNODES
  151.         : newMaxNodes) : 0);
  152. }
  153.  
  154. voiD Binder::atIns(unsigned n, const voiD D)
  155. {
  156.     voiDV newLinkS;
  157.     unsigned newLimit, i;
  158.  
  159.     if (!linkS || !D)
  160.         return voiD0;
  161.     if (nodes == limit)  {
  162.         if (limit == maxNodes)
  163.             return voiD0;
  164.         newLimit = (maxNodes - delta > limit)?
  165.             limit + delta : maxNodes;
  166.         if ((newLinkS = new voiD[newLimit])
  167.             == voiDV0) return voiD0;
  168.         if ((i = limit - first) > nodes)
  169.             i = nodes;
  170.         memcpy(newLinkS,&linkS[first],
  171.             sizeof(linkS[0])*i);
  172.         /* copy wrap around */
  173.         if (i < nodes)
  174.             memcpy(&newLinkS[i],linkS,
  175.                 sizeof(linkS[0])*(nodes-i));
  176.         /*
  177.             Compute next smaller linkS size
  178.             and threshold for shrinking.
  179.         */
  180.         lowLimit = limit;
  181.         lowThreshold = lowLimit - delta;
  182.         /* swap new for old */
  183.         delete linkS;
  184.         linkS = newLinkS;
  185.         limit = newLimit;
  186.         first = 0;
  187.     }
  188.     if (!Dattach(D))
  189.         return voiD0;
  190.     if (!n)  /* push */
  191.         linkS[first? --first
  192.             : (first = limit - 1)] = D;
  193.     else if (n >= nodes) /* insQ */
  194.         linkS[(first+(n=nodes))%limit] = D;
  195.     else  { /* insert interior */
  196.         i = (first + n) % limit;
  197.         if (i < first || !first)
  198.             /* move rear rightward */
  199.             memmove(&linkS[i+1],&linkS[i],
  200.                 sizeof(linkS[0])
  201.                 * (nodes-n));
  202.         else /* move front leftward */
  203.             memmove(&linkS[--first],&linkS[--i],
  204.                 sizeof(linkS[0])*(n+1));
  205.         linkS[i] = D;
  206.     }
  207.     nodes++;
  208.     if (n <= curNode)
  209.         curNode++;
  210.     flags &= ~BDR_SORTED;
  211.     return D;
  212. }
  213.  
  214. voiD Binder::atDel(unsigned n)
  215. {
  216.     voiDV newLinkS;
  217.     unsigned newLimit, i;
  218.     voiD D;
  219.  
  220.     if (!linkS || n >= nodes)
  221.         return voiD0;
  222.     D = linkS[(first+n)%limit];
  223.     if (!n)  {  /* pop */
  224.         if (++first >= limit)
  225.             first = 0;
  226.     }
  227.     else if (n != nodes-1)  {  /* del interior */
  228.         /* move front rightward */
  229.         memmove(&linkS[first+1],&linkS[first],
  230.             sizeof(linkS[0])*n);
  231.         first++;
  232.     }
  233.     if (--nodes == 0)
  234.         flags |= BDR_SORTED;
  235.     if (n < curNode)
  236.         curNode--;
  237.     else if (n == curNode)
  238.         curNode = nodes;
  239.     if (nodes < lowThreshold)  {
  240.         newLimit = lowLimit;
  241.         if ((newLinkS = new voiD[newLimit])
  242.             != voiDV0)  {
  243.             if ((i = limit - first) > nodes)
  244.                 i = nodes;
  245.             memcpy(newLinkS,&linkS[first],
  246.                 sizeof(linkS[0])*i);
  247.             /* copy wrap around */
  248.             if (i < nodes)
  249.                 memcpy(&newLinkS[i],linkS,
  250.                     sizeof(linkS[0])
  251.                     *(nodes-i));
  252.             /*
  253.                 Compute next smaller linkS
  254.                 size and threshold for 
  255.                 shrinking.
  256.             */
  257.             if (lowLimit - delta > delta)
  258.                 lowLimit -= delta;
  259.             else
  260.                 lowLimit = delta;
  261.             lowThreshold = lowLimit - delta;
  262.             /* swap new for old */
  263.             delete linkS;
  264.             linkS = newLinkS;
  265.             limit = newLimit;
  266.             first = 0;
  267.         }
  268.     }
  269.     Ddetach(D);
  270.     return D;
  271. }
  272.  
  273. int Binder::allDel()
  274. {
  275.     if (!linkS)
  276.         return 0;
  277.     for (unsigned i = 0; i < nodes; /* no reinit */)
  278.         if (!atDel(i))
  279.             i++;
  280.     return (nodes? 0 : 1);
  281. }
  282.  
  283. int Binder::allFree()
  284. {
  285.     if (!linkS)
  286.         return 0;
  287.     if (flags & BDR_OK_FREE)
  288.         for (unsigned i = 0; i < nodes; 
  289.             /* no reinit */)
  290.             if (!Dfree(atDel(i)))
  291.                 i++;
  292.     return (nodes? 0 : 1);
  293. }
  294.  
  295. voiD Binder::atPut(unsigned n, const voiD D)
  296. {
  297.     if (linkS && D && (n < nodes))
  298.         if (Dattach(D))  {
  299.             flags &= ~BDR_SORTED;
  300.             voiD& N = linkS[(first+n)%limit];
  301.             Ddetach(N);
  302.             DFREE(N);
  303.             return (N=D);
  304.         }
  305.     return voiD0;
  306. }
  307.  
  308. voiD Binder::atGet(unsigned n)
  309. {
  310.     return ((linkS && (n < nodes))?
  311.         linkS[(first+n)%limit] : voiD0);
  312. }
  313.  
  314. voiD Binder::atXchg(unsigned n, const voiD D)
  315. {
  316.     if (linkS && D && (n < nodes))
  317.         if (Dattach(D))  {
  318.             flags &= ~BDR_SORTED;
  319.             voiD& N = linkS[(first+n)%limit];
  320.             voiD oldD = N;
  321.             N = D;
  322.             Ddetach(oldD);
  323.             return oldD;
  324.         }
  325.     return voiD0;
  326. }
  327.  
  328. unsigned Binder::index(const voiD D)
  329. {
  330.     unsigned i;
  331.  
  332.     if (linkS && D)
  333.         for (i = 0; i < nodes; i++)
  334.             if (D == linkS[(first+i)%limit])
  335.                 return i;
  336.     return BDR_NOTFOUND;
  337. }
  338.  
  339. int Binder::forEach(BDRforEachBlocK B, voiD M, voiD A)
  340. {
  341.     unsigned i;
  342.  
  343.     if (!linkS || !B || !nodes)
  344.         return 0;
  345.     for (i = 0; i < nodes; i++)
  346.         (*B)(linkS[(first+i)%limit],M,A);
  347.     return 1;
  348. }
  349.  
  350. unsigned Binder::firstThat(BDRdetectBlocK B, voiD M)
  351. {
  352.     unsigned i;
  353.  
  354.     if (linkS && B)
  355.         for (i = 0; i < nodes; i++)
  356.             if ((*B)(linkS[(first+i)%limit],M))
  357.                 return i;
  358.     return BDR_NOTFOUND;
  359. }
  360.  
  361. unsigned Binder::lastThat(BDRdetectBlocK B, voiD M)
  362. {
  363.     unsigned i;
  364.  
  365.     if (linkS && B && nodes)
  366.         for (i = nodes; i--; /* no reinit */)
  367.             if ((*B)(linkS[(first+i)%limit],M))
  368.                 return i;
  369.     return BDR_NOTFOUND;
  370. }
  371.  
  372. int Binder::collect(BDRcollectBlocK B, BindeR R,
  373.     voiD M, voiD A)
  374. {
  375.     unsigned i;
  376.  
  377.     if (!linkS || !B || !R)
  378.         return 0;
  379.     for (i = 0; i < nodes; i++)
  380.         (*B)(linkS[(first+i)%limit],R,M,A);
  381.     return 1;
  382. }
  383.  
  384.  
  385. /*  FlexList like primitives:  */
  386.  
  387. unsigned Binder::CurNode()
  388. {
  389.     return ((curNode < nodes)?
  390.         curNode : BDR_NOTFOUND);
  391. }
  392.  
  393. int  Binder::setCurNode(unsigned n)
  394. {
  395.     return ((curNode = ((n > nodes)? nodes : n))
  396.         < nodes);
  397. }
  398.  
  399. Binder& Binder::operator<<(Binder& (*manipulator)
  400.         (Binder& B))
  401. {
  402.     return (manipulator? (*manipulator)(*this)
  403.         : *this);
  404. }
  405.  
  406. voiD Binder::ins(const voiD D)
  407. {
  408.     if (atIns(curNode+1,D))  {
  409.         if (++curNode >= nodes)
  410.             curNode = nodes - 1;
  411.         return D;
  412.     }
  413.     return voiD0;
  414. }
  415.  
  416. voiD Binder::insSort(const voiD D)
  417. {
  418.     unsigned low, mid, high;
  419.     voiD ok;
  420.  
  421. /*
  422.     The current node is left undefined if
  423.     anything fails, otherwise it is set to the
  424.     newly inserted node.
  425. */
  426.  
  427.     curNode = nodes;
  428.     if (!linkS || !D || nodes >= maxNodes || !comparE)
  429.         return voiD0;
  430.     if (!(flags & BDR_SORTED))
  431.         if (!sort())
  432.             return voiD0;
  433.     low = 0;
  434.     high = nodes;
  435.     while (low < high)  {
  436.         mid = low + ((high - low) >> 1);
  437.         if ((*comparE)(D,
  438.             linkS[(first+mid)%limit]) <= 0)
  439.             high = mid;
  440.         else
  441.             low = mid + 1;
  442.     }
  443.     if ((ok = atIns(high,D)) != voiD0)
  444.         curNode = high;
  445.     /*  atIns() resets sorted to zero  */
  446.     flags |= BDR_SORTED;
  447.     return ok;
  448. }
  449.  
  450. voiD Binder::del()
  451. {
  452.     voiD D;
  453.     unsigned n;
  454.  
  455.     if ((D = atDel(n=curNode)) != voiD0)
  456.         if (n--)
  457.             curNode = n;
  458.     return D;
  459. }
  460.  
  461. voiD Binder::next()
  462.     if (linkS)  {
  463.         if (curNode >= nodes)
  464.             curNode = 0;
  465.         else
  466.             curNode++;
  467.         if (curNode < nodes)
  468.             return linkS[(first+curNode)%limit];
  469.     }
  470.     return voiD0;
  471. }
  472.  
  473. voiD Binder::prev()
  474.     if (linkS)  {
  475.         if (curNode)  {
  476.             if (curNode > nodes)
  477.                 curNode = nodes;
  478.             curNode--;
  479.         }
  480.         else
  481.             curNode = nodes;
  482.         if (curNode < nodes)
  483.             return linkS[(first+curNode)%limit];
  484.     }
  485.     return voiD0;
  486. }
  487.  
  488. voiD Binder::findFirst(const voiD K)
  489. {
  490.     unsigned low, mid, high;
  491.     voiD D;
  492.  
  493. /*
  494.     The current node is left undefined if
  495.     anything fails, otherwise it is set to the
  496.     newly found node.
  497. */
  498.  
  499.     curNode = nodes;
  500.     if (!linkS || !K || !comparE || !nodes)
  501.         return voiD0;
  502.     if (flags & BDR_SORTED)  {
  503.         low = 0;
  504.         high = nodes;
  505.         while (low < high)  {
  506.             mid = low + ((high - low) >> 1);
  507.             if ((*comparE)(K,linkS[(first+mid)
  508.                 %limit]) <= 0)
  509.                 high = mid;
  510.             else
  511.                 low = mid + 1;
  512.         }
  513.         if (high < nodes)
  514.             if (!(*comparE)(K,linkS[(first+
  515.                 high)%limit]))
  516.                 return linkS[(first+
  517.                 (curNode = high))%limit];
  518.     }
  519.     else  {  /*  linear search!  */
  520.         while ((D = next()) != voiD0)
  521.             if (!(*comparE)(K,D))
  522.                 return D;
  523.     }
  524.     return voiD0;
  525. }
  526.  
  527. voiD Binder::findNext(const voiD K)
  528. {
  529.  
  530. /*
  531.     For sorted binders you must first call findFirst()
  532.     to insure consistent results!
  533. */
  534.  
  535.     voiD D;
  536.  
  537. /*
  538.     The current node is left undefined if
  539.     anything fails, otherwise it is set to the
  540.     newly found node.
  541. */
  542.  
  543.     if (!linkS || !K || !comparE)  {
  544.         curNode = nodes;
  545.         return voiD0;
  546.     }
  547.     while ((D = next()) != voiD0)
  548.         if (!(*comparE)(K,D))
  549.             return D;
  550.         else if (flags & BDR_SORTED)  {
  551.             curNode = nodes;
  552.             break; /*  Look no further!  */
  553.         }
  554.     return voiD0;
  555. }
  556.  
  557. voiD Binder::findLast(const voiD K)
  558. {
  559.     unsigned low, mid, high;
  560.     voiD D;
  561.  
  562. /*
  563.     The current node is left undefined if
  564.     anything fails, otherwise it is set to the
  565.     newly found node.
  566. */
  567.  
  568.     curNode = nodes;
  569.     if (!linkS || !K || !comparE || !nodes)
  570.         return voiD0;
  571.     if (flags & BDR_SORTED)  {
  572.         low = 0;
  573.         high = nodes;
  574.         while (low < high)  {
  575.             mid = low + ((high - low) >> 1);
  576.             if ((*comparE)(K,linkS[(first+mid)
  577.                 %limit]) < 0)
  578.                 high = mid;
  579.             else
  580.                 low = mid + 1;
  581.         }
  582.         if (high < nodes)
  583.             if (!(*comparE)(K,linkS[(first+
  584.                 high)%limit]))
  585.                 return linkS[(first+
  586.                 (curNode = high))%limit];
  587.     }
  588.     else  {  /*  linear search!  */
  589.         while ((D = prev()) != voiD0)
  590.             if (!(*comparE)(K,D))
  591.                 return D;
  592.     }
  593.     return voiD0;
  594. }
  595.  
  596. voiD Binder::findPrev(const voiD K)
  597. {
  598.  
  599. /*
  600.     For sorted binders you must first call findLast()
  601.     to insure consistent results!
  602. */
  603.  
  604.     voiD D;
  605.  
  606. /*
  607.     The current node is left undefined if
  608.     anything fails, otherwise it is set to the
  609.     newly found node.
  610. */
  611.  
  612.     if (!linkS || !K || !comparE)  {
  613.         curNode = nodes;
  614.         return voiD0;
  615.     }
  616.     while ((D = prev()) != voiD0)
  617.         if (!(*comparE)(K,D))
  618.             return D;
  619.         else if (flags & BDR_SORTED)  {
  620.             curNode = nodes;
  621.             break; /*  Look no further!  */
  622.         }
  623.     return voiD0;
  624. }
  625.  
  626. int   Binder::sort(BDRcomparE comparE)
  627. {
  628.     unsigned low, mid, high;
  629.     unsigned d;
  630.     voiD D;
  631.  
  632. /*
  633.     The current node is always reset to undefined
  634.     regardless of the outcome of sort.
  635. */
  636.  
  637.     curNode = nodes;
  638.     if (flags & BDR_SORTED)  {
  639.         if (this->comparE == comparE || !comparE)
  640.             return 1;
  641.     }
  642.     else if (!this->comparE && !comparE)
  643.         return 0;
  644.     if (comparE)  {
  645.         this->comparE = comparE;
  646.         flags &= ~BDR_SORTED;
  647.     }
  648.     if (!nodes)
  649.         return (flags |= BDR_SORTED);
  650.     if (!linkS)
  651.         return 0;
  652.     if (first)  { /* form contiguous block at front */
  653.         d = (first + nodes) % limit;
  654.         if (d > first)
  655.             memmove(linkS,&linkS[first],
  656.                 sizeof(linkS[0])*nodes);
  657.         else if (d < first)
  658.             memmove(&linkS[d],&linkS[first],
  659.                 sizeof(linkS[0])
  660.                 *(limit-first));
  661.         /* else array is full/contiguous */
  662.         first = 0;
  663.     }
  664.     for (high = d = 1; d < nodes; high = ++d)  {
  665.         low = 0;
  666.         D = linkS[d];
  667.         while (low < high)  {
  668.             mid = low + ((high - low) >> 1);
  669.             if ((*this->comparE)(D,
  670.                 linkS[mid]) <= 0)
  671.                 high = mid;
  672.             else
  673.                 low = mid + 1;
  674.         }
  675.         if (high < d)  {
  676.             memmove(&linkS[high+1],&linkS[high],
  677.                 sizeof(linkS[0])*(d-high));
  678.             linkS[high] = D;
  679.         }
  680.     }
  681.     return (flags |= BDR_SORTED);
  682. }
  683.